package com.liquidcode.cellular;

import javax.microedition.khronos.opengles.GL10;

import com.liquidcode.cellular.R;

import android.util.Log;

import utility.VecHelper;
import utility.vec2;

import entities.CPlayer;
import entities.CSprite;

public class CInputManager 
{
	private static CInputManager mInstance = null; 
	private CSprite m_stickBackground = null;
	private CSprite m_stick = null;
	private int m_screenWidth;
	private int m_screenHeight;
	private vec2 m_stickBackgroundPosition;
	private vec2 m_stickButtonPosition;
	private vec2 m_vDirection = null;
	private float m_playerRotation = 0.0f;
	private vec2 m_backOffset;
	private vec2 m_stickOffset;
	private boolean m_touchingStick = false;
	private float offsetX = 0.0f;
	private vec2 m_latestTouch;
	private float ACCEL_MIN_THRESHOLD = 1.0f;
	
	
	public static CInputManager getInstance()
	{
		if( mInstance == null )
			mInstance = new CInputManager();
		return mInstance;
	}
	
	private CInputManager()
	{
		m_stickBackgroundPosition = new vec2();
		m_stickButtonPosition = new vec2();
		m_vDirection = new vec2();
		m_backOffset = new vec2();
		m_stickOffset = new vec2();
		m_latestTouch = new vec2();
	}
	
	public void InitManagerWithScreen(int w, int h)
	{
		
//		m_stickBackground = new CSprite();
//		Texture t = CAssetManager.GetInstance().getTexture(R.drawable.joy_back);
//		m_stickBackground.setTexture(t, true);
//		
//		m_stick = new CSprite();
//		t = CAssetManager.GetInstance().getTexture(R.drawable.joy_button);
//		m_stick.setTexture(t, true);
//		
		m_screenWidth = w;
		m_screenHeight = h;
//		m_stickBackgroundPosition.setX(m_stickBackground.getWidth()*0.5f);
//		m_stickBackgroundPosition.setY(m_screenHeight - m_stickBackground.getHeight()*0.5f);
//		
//		m_stickButtonPosition.setX(m_stickBackgroundPosition.getX());
//		m_stickButtonPosition.setY(m_stickBackgroundPosition.getY());
//		
//		m_backOffset.setX(m_stickBackground.getWidth()*0.5f);
//		m_backOffset.setY(m_stickBackground.getHeight()*0.5f);
		//m_stickOffset.setX(m_stick.getWidth()*0.5f);
		//m_stickOffset.setY(m_stick.getHeight()*0.5f);
	}
	
	public void Update(float dt)
	{
		//m_stickBackgroundPosition.setX(CCamera.getInstance().getViewport().min.getX() + m_backOffset.getX());
		//m_stickBackgroundPosition.setY(CCamera.getInstance().getViewport().max.getY() - m_backOffset.getY());
		// if we arent touching the stick at all just reset it back to the center position 
//		if( m_touchingStick == false )
//		{
//			m_stickButtonPosition.setX(m_stickBackgroundPosition.getX());
//			m_stickButtonPosition.setY(m_stickBackgroundPosition.getY());
//		}
//		else
//		{
//			m_stickButtonPosition.setX(m_stickBackgroundPosition.getX() - m_stickOffset.getX());
//			m_stickButtonPosition.setY(m_stickBackgroundPosition.getY() - m_stickOffset.getY());
//		}
		
	}
	
	public void Render(GL10 gl)
	{
		RenderJoystickBackground(gl);
		RenderJoystick(gl);
	}
	
	public void ResetStickToCenter()
	{
		m_stickButtonPosition.setX(m_stickBackgroundPosition.getX());
		m_stickButtonPosition.setY(m_stickBackgroundPosition.getY());
		m_stickOffset.setX(0.0f);
		m_stickOffset.setY(0.0f);
		SendUpdateToPlayer();
		m_touchingStick = false;
	}
	public boolean CheckJoystickTouch(float x, float y)
	{
		int xPos = (int) (m_stickButtonPosition.getX());
		int yPos = (int) (m_stickButtonPosition.getY());
		
		// we need to change the x/y touch position to the viewport space. 
//		float xRatio = x/m_screenWidth;
//		float yRatio = y/m_screenHeight;
//		
//		float offsetX = (xRatio*m_screenWidth);
//		float offsetY = (yRatio*m_screenHeight);
//		x = (CCamera.getInstance().getViewport().min.getX() + offsetX);
//		y = (CCamera.getInstance().getViewport().min.getY() + offsetY);
		
		
		if( x > (xPos - m_stick.getWidth()*0.5f) && x < (xPos + m_stick.getWidth()) &&
				y > (yPos-m_stick.getHeight()*0.5f) && y < (yPos + m_stick.getHeight()))
		{
			m_touchingStick = true;
			// now move the joystick to the correct position
			float xDiff = m_stickButtonPosition.getX() - x;
			float yDiff = m_stickButtonPosition.getY() - y;
			m_stickOffset.setX(xDiff);
			m_stickOffset.setY(yDiff);
			
			m_playerRotation = (float) ((Math.atan2(yDiff, xDiff) * 180 / Math.PI) - 180 ) * -1.0f;
			

			// the direction vector
			m_vDirection = VecHelper.subtract(new vec2(x, y), m_stickBackgroundPosition);
			m_playerRotation = VecHelper.angleFromDirection(m_vDirection);
			m_playerRotation = (float) (m_playerRotation * (180/Math.PI)) - 90.0f;
			
			//Log.d("ROTATION", String.format("%f", m_playerRotation));
			
			float newTouchX = (float) (x + Math.cos(m_playerRotation * (Math.PI/180)) * x/70);
			float newTouchY = (float) (y + Math.sin(m_playerRotation * (Math.PI/180)) * y/70);
			
			// Touch detection based on a viewport system 
			//m_stickButtonPosition.setX(m_stickBackgroundPosition.getX() - m_stickOffset.getX());
			//m_stickButtonPosition.setY(m_stickBackgroundPosition.getY() - m_stickOffset.getY());
			m_stickButtonPosition.setX(newTouchX);
			m_stickButtonPosition.setY(newTouchY);
			
			CalculatePlayerMovement(m_vDirection);
			SendUpdateToPlayer();
			return true;
		}
		
		return false;
	}
	
	public void HandleAccelerometerMovement(float xVal, float yVal)
	{
		// because the game is in landscape the xAccel actually moves in the "y" direction and same with yAccel
		float x = Math.abs(xVal);
		float y = Math.abs(yVal);
		CPlayer.getInstance().EnablePlayerMovement();
		CPlayer.getInstance().setVelX(-yVal);
		CPlayer.getInstance().setVelY(-xVal);

//		if( x > ACCEL_MIN_THRESHOLD && y > ACCEL_MIN_THRESHOLD )
//		{
//			CPlayer.getInstance().EnablePlayerMovement();
//			CPlayer.getInstance().setVelX(-yVal);
//			CPlayer.getInstance().setVelY(-xVal);
//		}
//		else if( x > ACCEL_MIN_THRESHOLD )
//		{
//			CPlayer.getInstance().EnablePlayerMovement();
//			CPlayer.getInstance().setVelX(-yVal);
//		}
//		else if( y > ACCEL_MIN_THRESHOLD )
//		{
//			CPlayer.getInstance().EnablePlayerMovement();
//			CPlayer.getInstance().setVelY(-xVal);
//		}
//		else
//		{
//			CPlayer.getInstance().DisablePlayerMovement();
//			return;
//		}
//		
		
	}
	
	private void CalculatePlayerMovement(vec2 direction)
	{
		CPlayer.getInstance().setVelX(direction.getX());
		CPlayer.getInstance().setVelY(direction.getY());
	}
	
	private void SendUpdateToPlayer()
	{
		//CPlayer.getInstance().setRotation(m_playerRotation);
	}

	public void RenderJoystick(GL10 gl)
	{
		gl.glPushMatrix();
		gl.glLoadIdentity();
		
		// translate the object
		gl.glScalef(1.0f, 1.0f, 1.0f);
		gl.glTranslatef(m_stickButtonPosition.getX(), m_stickButtonPosition.getY(), 0.0f);

		// set the textures
		gl.glEnable(GL10.GL_TEXTURE_2D);
		gl.glBindTexture(GL10.GL_TEXTURE_2D, m_stick.getTextureID());
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		// Point to our buffers
		gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, m_stick.getTexBuffer());

		// draw
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, m_stick.getVB());
		gl.glDrawElements(GL10.GL_TRIANGLES, m_stick.getNumIndices(),
				GL10.GL_UNSIGNED_SHORT, m_stick.getIB());

		/// pop
		gl.glPopMatrix();
	}
	
	public void RenderJoystickBackground(GL10 gl)
	{
		gl.glPushMatrix();
		gl.glLoadIdentity();
		
		// translate the object
		gl.glScalef(1.0f, 1.0f, 1.0f);
		gl.glTranslatef(m_stickBackgroundPosition.getX(), m_stickBackgroundPosition.getY(), 0.0f);

		// set the textures
		gl.glEnable(GL10.GL_TEXTURE_2D);
		gl.glBindTexture(GL10.GL_TEXTURE_2D, m_stickBackground.getTextureID());
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		// Point to our buffers
		gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, m_stickBackground.getTexBuffer());

		// draw
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, m_stickBackground.getVB());
		gl.glDrawElements(GL10.GL_TRIANGLES, m_stickBackground.getNumIndices(),
				GL10.GL_UNSIGNED_SHORT, m_stickBackground.getIB());

		// pop
		gl.glPopMatrix();
	}
	
	
	// Accessors 
	public float getPlayerRotation() { return m_playerRotation; } 
	public vec2 getDirection() { return m_vDirection; }
	public vec2 getLatestTouch() { return m_latestTouch; }
	public float getScreenWidth() { return m_screenWidth; }
	public float getScreenHeight() { return m_screenHeight; }
	
	// Mutators
	public void setLatestTouch(float x, float y)
	{
		m_latestTouch.setX(x);
		m_latestTouch.setY(y);
	}
	
	
}
